﻿using System;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Text;
using System.Diagnostics;

namespace ServerControler
{
    public class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("================Socket Started======================");

            //建立一个子线程，用于创建Socket来监听策略请求和发送。
            ThreadStart pcts = new ThreadStart(PolicyThread);
            Thread policythread = new Thread(pcts);
            policythread.Start();

            //建立一个子线程，用于创建Socket来监听信息请求和发送。
            ThreadStart infots = new ThreadStart(InfoThread);
            Thread infothread = new Thread(infots);
            infothread.Start();

            // Hidden the console window.
            HiddenConsoleWindow();
        }

        private static void HiddenConsoleWindow()
        {
            // min the consolw window
            Console.Title = "PTRemoteServer";
            IntPtr ParenthWnd = new IntPtr(0);
            IntPtr et = new IntPtr(0);
            ParenthWnd = Win32API.FindWindow(null, "PTRemoteServer");
            //隐藏本dos窗体, 0: 后台执行；1:正常启动；2:最小化到任务栏；3:最大化
            Win32API.ShowWindow(ParenthWnd, 2);
        }

        //监听策略请求和发送策略请求方法
        static void PolicyThread()
        {
            //创建一个Socket用来监听943（固定的）端口的策略请求       
            Socket policy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            policy.Bind(new IPEndPoint(IPAddress.Any, 943));
            policy.Listen(10);

            //无限循环监听
            while (true)
            {
                if (policy.Blocking)//如果Socket是阻止模式的（这个东西实际上可以用不）
                {
                    //创建Socket，用来获取监听Socket的第一个Socket链接
                    Socket _policy = policy.Accept();

                    //定义一个字符串，该字符串与Silverlight发送过来的请求字符串一样。
                    string policyRequestString = "<policy-file-request/>";

                    //定义一个字节数组
                    byte[] b = new byte[policyRequestString.Length];

                    //将客户端发送过来，服务器接收到的字节数组存入b中
                    _policy.Receive(b);

                    //将接收到的字节数组转换成字符串
                    string requeststring = System.Text.Encoding.UTF8.GetString(b, 0, b.Length);

                    //显示客户端发送的字符串
                    Console.WriteLine(requeststring);

                    //比对客户端发送过来的字符串是否和之前定义的额定好的策略请求字符串相同，如果相同，说明该请求是一个策略请求。
                    if (requeststring == policyRequestString)
                    {
                        //如果客户端发送的是一个策略请求，服务器发送策略文件到客户端
                        SendPolicy(_policy);

                        Console.WriteLine("Policy File have sended");

                        //关闭当前连接Socket
                        _policy.Close();
                    }
                    else// 否则，显示错误
                    {
                        Console.WriteLine("not a sure request string!");
                    }

                }

            }
        }

        //发送策略文件的方法
        //参数是传递进来的Socket连接
        static void SendPolicy(Socket socket)
        {
            //创建一个文件流，该文件留指定代开一个策略文件，至于策略文件的格式，MS的Silverlight有详细说明和配置方法
            // FileStream fs = new FileStream, FileMode.Open);
            FileStream fs = new FileStream("PolicyFile.xml", FileMode.Open);
            int length = (int)fs.Length;
            byte[] bytes = new byte[length];
            //将策略文件流读到上面定义的字节数组中
            fs.Read(bytes, 0, length);
            //关闭文件流
            fs.Close();
            //其策略文件的字节数组发送给客户端
            socket.Send(bytes, length, SocketFlags.None);
        }

        //监听信息请求和发送信息方法
        static void InfoThread()
        {
            //创建一个Socket用于监听4502端口，获取接收客户端发送过来的信息
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(new IPEndPoint(IPAddress.Any, 4502));
            socket.Listen(10);

            //无线循环监听
            while (true)
            {
                //创建Socket，用来获取监听Socket的第一个Socket链接
                Socket _socket = socket.Accept();

                //定义一个字节数组
                // byte[] b = new byte[8];
                byte[] b = new byte[40000];
                //将客户端发送过来，服务器接收到的字节数组存入b中
                _socket.Receive(b);

                //将接收到的字节数组转换成字符串
                string requeststring = System.Text.Encoding.UTF8.GetString(b, 0, b.Length);

                string requestCommand = requeststring.Substring(0, 11);
                if (requestCommand == CommandNames.SLTCASELIST.ToString())
                {
                    // todo need check wfp or sl assembly type.
                    string caseList = Case.GetCaseList(Utility.SLAssemblyPath);
                    _socket.Send(Encoding.UTF8.GetBytes(CommandNames.SLTCASELIST.ToString() + caseList));
                }
                else if (requestCommand == CommandNames.WPFCASELIST.ToString())
                {
                    // todo need check wfp or sl assembly type.
                    string caseList = Case.GetCaseList(Utility.WPFAssemblyPath);
                    _socket.Send(Encoding.UTF8.GetBytes(CommandNames.WPFCASELIST.ToString() + caseList));
                }
                else if (requestCommand == CommandNames.DOWPFPFTEST.ToString())
                {
                    // getstring's length
                    string[] tempStr = requeststring.Split(';');
                    string len = tempStr[tempStr.Length - 2];

                    int length = int.Parse(len);
                    string cases = requeststring.Substring(11, length - 11);

                    RebuildWPFProject(Utility.WPFRebuildBatFilePath, cases);
                }
                else if (requestCommand == CommandNames.DOSLTPFTEST.ToString())
                {
                    // getstring's length
                    string[] tempStr = requeststring.Split(';');
                    string len = tempStr[tempStr.Length - 2];

                    int length = int.Parse(len);
                    string cases = requeststring.Substring(11, length - 11);

                    RebuildSLProject(Utility.SLRebuildBatFilePath, cases);
                }
                else if (requestCommand == CommandNames.ISSERVEBUSY.ToString())
                {
                    // check is server busy.
                    if (_isServerBusy)
                    {
                        _socket.Send(Encoding.UTF8.GetBytes(CommandNames.SERVERBUSYY.ToString()));
                    }
                    else
                    {
                        _socket.Send(Encoding.UTF8.GetBytes(CommandNames.SERVEUNBUSY.ToString()));
                    }
                }

                //关闭当前Socket连接
                _socket.Close();
            }
        }

        private static void RunTest(string cases, string configFile)
        {
            // get arguments
            StringBuilder sb = new StringBuilder();
            sb.Append("\"/ConfigFile=" + configFile + "\"");
            sb.Append(" /CaseList=" + cases);
            ProcessStartInfo startInfo = new ProcessStartInfo(Utility.PTesterPath);
            startInfo.Arguments = sb.ToString();

            Process currentTestProcess = Process.Start(startInfo);
            currentTestProcess.EnableRaisingEvents = true;
            currentTestProcess.Exited += (sender, e) =>
            {
                _isServerBusy = false;
            };
        }

        private static bool _isServerBusy = false;

        private static void RebuildWPFProject(string wpfBatFile, string cases)
        {
            Process rebuildProject = new Process();
            rebuildProject.StartInfo.UseShellExecute = true;
            rebuildProject.StartInfo.FileName = wpfBatFile;
            rebuildProject.StartInfo.CreateNoWindow = true;
            rebuildProject.EnableRaisingEvents = true;
            rebuildProject.Exited += (sender, e) =>
            {
                RunTest(cases, Utility.WPFTesterConfigFilePath);
            };
            rebuildProject.Start();
            _isServerBusy = true;
        }

        private static void RebuildSLProject(string slBatFile, string cases)
        {
            Process rebuildProject = new Process();
            rebuildProject.StartInfo.UseShellExecute = true;
            rebuildProject.StartInfo.FileName = slBatFile;
            rebuildProject.StartInfo.CreateNoWindow = true;
            rebuildProject.EnableRaisingEvents = true;
            rebuildProject.Exited += (sender, e) =>
            {
                RunTest(cases, Utility.SLTesterConfigFilePath);
            };
            rebuildProject.Start();
            _isServerBusy = true;
        }
    
    }
}
